//
//  DeviceTableDataSource.m
//  MusicAnalyzer
//
//  Created by jiro on 12/03/24.
//  Copyright 2012 jiro music. All rights reserved.
//

#import "DeviceTableDataSource.h"
#import "../../../Common/DeviceSystem.h"

@implementation DeviceTableDataSource

@synthesize deviceInfos;
@synthesize displayOnlyMidiDevice;

- (id) init
{
	self = [ super init ];
	deviceInfos = new std::vector< sc::DeviceInfo* >();
	return self;
}

-(void) dealloc
{
	[ self clearDeviceInfos ];
	delete deviceInfos;
	deviceInfos = NULL;
	[ super dealloc ];
}

- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{
	if ( displayOnlyMidiDevice )
	{
		int midiDeviceCount = 0;
		for ( int i = 0, count = deviceInfos->size(); i < count; i++ )
		{
			const sc::DeviceInfo* info = deviceInfos->at( i );
			if ( info->IsMidiDevice() )
			{
				midiDeviceCount++;
			} 
		}
		return midiDeviceCount;
	}
	else
	{
		return deviceInfos->size();
	}
}

- (id)tableView: (NSTableView *) tableView
	objectValueForTableColumn: (NSTableColumn *) tableColumn 
	row: (NSInteger) row
{
	const sc::DeviceInfo* info = NULL;
	const sc::UsbDeviceInfo* usbDeviceInfo = NULL;
	if ( displayOnlyMidiDevice )
	{
		info = [ self usbMidiDeviceInfoOrderAt: row ];
	}
	else
	{
		info = deviceInfos->at( row );
	}
	usbDeviceInfo = dynamic_cast< const sc::UsbDeviceInfo* >( const_cast< sc::DeviceInfo* >( info ) );

	id identifier = [ tableColumn identifier ];
	if ( [ identifier isEqualToString: @"midiDeviceFlag" ] )
	{
		if ( usbDeviceInfo->IsMidiDevice() )
		{
			return [ NSNumber numberWithInt: NSOnState ];
		}
		else
		{
			return [ NSNumber numberWithInt: NSOffState ];
		}
	}
	else if ( [ identifier isEqualToString: @"vendorName" ] )
	{
		return [ NSString stringWithCString: usbDeviceInfo->GetVendorName().c_str() encoding: NSUTF8StringEncoding ];
	}
	else if ( [ identifier isEqualToString: @"productName" ] )
	{
		return [ NSString stringWithCString: usbDeviceInfo->GetProductName().c_str() encoding: NSUTF8StringEncoding ];
	}
	else
	{
		NSAssert( NO, @"unknown column name" ); 
		return @"";
	}

}

- (void) reloadData
{
	[ tableView reloadData ];
}

- (void) addDeviceInfo: ( sc::DeviceInfo* ) info
{
	//	re-generate to manage UsbDeviceInfo's instance
	sc::UsbDeviceInfo* newInfo = nil;
	if ( sc::DeviceInfo::Type_UsbMidiDevice == info->GetType() )
	{
		newInfo = new sc::UsbMidiDeviceInfo( * dynamic_cast< const sc::UsbMidiDeviceInfo* >( info ) );
	}
	else if ( sc::DeviceInfo::Type_UsbDevice == info->GetType() )
	{
		newInfo = new sc::UsbDeviceInfo( * dynamic_cast< const sc::UsbDeviceInfo* >( info ) );
	}
	else
	{
		@throw( @"DeviceTableDataSource - (void) addDeviceInfo: ( const sc::DeviceInfo* ) info CAN ONLY ACCEPT USBMIDI AND USB DEVICE" );
	}
//	NSLog( @"- (void) addDeviceInfo: ( const sc::DeviceInfo* ) info: %08x", newInfo );
	deviceInfos->push_back( static_cast< sc::UsbDeviceInfo* >( newInfo ) );
	[ self reloadData ];
}

- (void) addDeviceInfos: ( const std::vector< sc::DeviceInfo* >* ) infos
{
	for ( std::vector< sc::DeviceInfo* >::iterator iter = deviceInfos->begin() ;
		  iter != deviceInfos->end();
		  iter++ )
	{
		[ self addDeviceInfo: (sc::DeviceInfo* ) ( * iter ) ];
	}
}

- (void) setDisplayOnlyMidiDevice: (BOOL) YesOrNo
{
	displayOnlyMidiDevice = YesOrNo;
}

- (sc::DeviceInfo*) usbMidiDeviceInfoOrderAt: (int) order
{
	int midiDeviceInfoIndex = 0;
	for ( int i = 0, count = deviceInfos->size(); i < count; i++ )
	{
		if ( ! deviceInfos->at( i )->IsMidiDevice() )
		{
			continue;
		}
		if ( midiDeviceInfoIndex == order )
		{
			return deviceInfos->at( i );
		}
		midiDeviceInfoIndex++;
	}
	NSAssert( NO, @"order is out of order" );
	return nil;
}

- (void) selectRowOf: ( const sc::DeviceInfo* ) info
{
	if ( NO == [ self isDeviceInfoDisplayed: info ] )
	{
		return;
	}

	NSMutableIndexSet* indexSet = [ [ NSMutableIndexSet alloc ] init ]; 
	NSUInteger index = 0;
	for ( int i = 0, count = deviceInfos->size(); i < count; i++ )
	{
		const sc::DeviceInfo* deviceInfo = deviceInfos->at( i );
		
		if ( NO == [ self isDeviceInfoDisplayed: deviceInfo ] )
		{
			continue;
		}
		if ( deviceInfo == info )
		{
			[ indexSet addIndex: index ];
			break;
		}
		index++;
	}
	if ( [ indexSet count ] > 0 )
	{
		[ tableView selectRowIndexes: indexSet byExtendingSelection: NO ];
	}
}

- (sc::DeviceInfo*) selectedDeviceInfo
{
	int index = [ tableView selectedRow ];
	if ( -1 == index )
	{
		return nil;
	}
	if ( displayOnlyMidiDevice )
	{
		return [ self usbMidiDeviceInfoOrderAt: index ];
	}
	return deviceInfos->at( index );
}

- (void) deselectAll
{
	[ tableView deselectAll: self ];
}

- (void) clearDeviceInfos
{
	for ( int i = 0, count = deviceInfos->size(); i < count; i++ )
	{
		sc::DeviceInfo* info = deviceInfos->at( i );
		delete info;
		deviceInfos->at( i ) = NULL;
	}
	deviceInfos->clear();
}

- (BOOL) isDeviceInfoDisplayed: ( const sc::DeviceInfo* ) info
{
	if ( displayOnlyMidiDevice )
	{
		if ( info->IsMidiDevice() )
		{
			return YES;
		}
		return NO;
	}
	return YES;
}

- (std::vector< sc::DeviceInfo*>*) getDeviceInfos
{
	return deviceInfos;
}

@end
